package com.example.demo.security;

import com.example.demo.domain.User;
import com.example.demo.core.entity.Menu;
import com.example.demo.core.entity.Permission;
import com.example.demo.core.entity.Role;
import com.example.demo.core.service.RoleService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.PermissionEvaluator;
import org.springframework.security.authentication.AnonymousAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Component;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

@Component
public class UserPermissionEvaluator implements PermissionEvaluator {

    @Autowired
    private RoleService roleService;

    /**
     * hasPermission鉴权方法
     * 这里仅仅判断PreAuthorize注解中的权限表达式
     * 实际中可以根据业务需求设计数据库通过targetUrl和permission做更复杂鉴权
     * @Param  authentication  用户身份(在使用hasPermission表达式时Authentication参数默认会自动带上)
     * @Param  url 请求u路径
     * @Param  path 请求路径权限
     * @Return boolean 是否通过
     */
    @Override
    public boolean hasPermission(Authentication authentication, Object path, Object permission) {
//        System.out.println("hasPermission");
        // 匿名/未认证，无权限
        if(authentication instanceof AnonymousAuthenticationToken)
            return denyHandler();

        // 获取当前用户的角色(role)
        User user = (User)authentication.getPrincipal();
        Integer roleId = user.getRoleId();
        Role role = roleService.getRoleById(roleId);
//        System.out.println(
//                "UserPermissionEvaluator: " +
//                " 角色id："  + role.getId()  +
//                " 角色名称：" + role.getName()
//
//        );

        //System.out.println(path.toString());
        //System.out.println(permission.toString());
        // 1. 检查角色的菜单列表
        Set<Menu> menus = role.getMenus();
        List<String> menuPaths = new ArrayList<>();
        for(Menu menu : menus){
            menuPaths.add(menu.getPath());
        }
        // 检查路径权限
        if(!menuPaths.contains(path.toString())){
            System.out.println("当前角色路径列表:" + menuPaths);
            System.out.println("当前用户请求路径" + path);
            return denyHandler();
        }

        // 2. 检查角色的权限列表
        Set<Permission> permissions = role.getChildren();
        List<String> permissionStrings = new ArrayList<>();
        for(Permission p : permissions){
            permissionStrings.add(p.getPath());
        }
        // 检查权限
        if(!permissionStrings.contains(permission.toString())){
            System.out.println("当前角色权限列表:" + permissionStrings);
            System.out.println("当前请求所需权限" + permission);
            return denyHandler();
        }

        return authorizedHandler();
    }

    public boolean authorizedHandler(){
//        System.out.println("authorizeHandler");
        return true;
    }

    public boolean denyHandler(){
//        System.out.println("denyHandler");
        return false;
    }

    @Override
    public boolean hasPermission(Authentication authentication, Serializable serializable, String s, Object o) {
        System.out.println("hasPermission2");
        return false;
    }
}
